﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Wise.Util
{
    public static class NullHelper
    {
        /// <summary>
        /// 将某个对象转换成可空类型
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="objSource">当T为Boolen时，可以为整型、字符串、浮点型</param>
        /// <returns></returns>
        public static Nullable<T> ParseToNullable<T>(object objSource) where T : struct
        {
            var type = typeof(Nullable<T>);
            return objSource.ChangeTo(type);
        }

        /// <summary>
        /// 转换成值类型或默认值
        /// </summary>
        /// <param name="objSource"></param>
        /// <returns></returns>
        public static T Parse<T>(object objSource) where T : struct
        {
            return objSource.ChangeTo(typeof(T));
        }

        /// <summary>
        /// 判断是否是可空类型
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static bool IsNullableType(this Type type)
        {
            if (type == null) throw new ArgumentNullException();
            if (!type.IsValueType) return false;
            return (type.IsGenericType && type.GetGenericTypeDefinition().Equals(typeof(Nullable<>)));
        }

        public static bool IsNullable(this Type type)
        {
            return IsNullableType(type);
        }

        /// <summary>
        /// 将可空类型解压成基础值类型
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static Type UnpackNullableType(this Type type)
        {
            if (!IsNullableType(type)) return type;
            return type.GetGenericArguments().FirstOrDefault() ?? type;
        }

        /// <summary>
        /// 将可空类型解压成基础值类型
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static Type UnpackNullable(this Type type)
        {
            if (!IsNullableType(type)) return type;
            return type.GetGenericArguments().FirstOrDefault() ?? type;
        }


        /// <summary>
        /// 检测是否是数据库的空类型
        /// </summary>
        /// <param name="objSource"></param>
        /// <returns></returns>
        public static bool IsDbNull(object objSource)
        {
            return objSource == null || objSource == DBNull.Value || objSource.GetType() == typeof(Object);
        }

        /// <summary>
        /// 判断是否是Javascript语言中的空值
        /// </summary>
        /// <param name="objValue"></param>
        /// <returns></returns>
        public static bool IsJsNull(object objValue)
        {
            if (objValue == null)
                return true;
            if (objValue is string)
            {
                string str = (string)objValue;
                return str.Equals("undefined") || str.Equals("null");
            }
            return false;
        }

        /// <summary>
        /// 判断是否是字符串空值
        /// </summary>
        /// <param name="objSource"></param>
        /// <returns></returns>
        public static bool IsStringNull(object objSource)
        {
            if (objSource == null) return true;
            if (objSource is string)
            {
                return string.IsNullOrEmpty((string)objSource);
            }
            return false;
        }

        static readonly DateTime _MIN_DATE = new DateTime();

        /// <summary>
        /// 检测是否是空的日期
        /// </summary>
        /// <param name="objValue"></param>
        /// <returns></returns>
        public static bool IsDateNull(object objValue)
        {
            if (objValue is DateTime)
            {
                DateTime dt = (DateTime)objValue;
                return dt == DateTime.MinValue || dt == _MIN_DATE;
            }
            return objValue == null;
        }

        /// <summary>
        /// 检测值是否是null或默认值，如果是默认值也判定为NULL
        /// </summary>
        /// <param name="objValue"></param>
        /// <returns></returns>
        public static bool IsAmsNull(object objValue)
        {
            if (objValue == null)
            {
                return true;
            }
            if (objValue is string)
            {
                return string.IsNullOrWhiteSpace(objValue.ToString());
            }
            else
            {
                Type objType = objValue.GetType();
                if (objType.IsValueType)
                {
                    if (objType == typeof(Guid) || objType == typeof(Guid?))
                    {
                        return Guid.Empty == (Guid)objValue;
                    }
                    else if (objType == typeof(int) || objType == typeof(int?))
                    {
                        return 0 == (int)objValue;
                    }
                    else if (objType == typeof(decimal) || objType == typeof(decimal?))
                    {
                        return 0M == (decimal)objValue;
                    }
                    else if (objType == typeof(float) || objType == typeof(float?))
                    {
                        return 0f == (float)objValue;
                    }
                    else if (objType == typeof(double) || objType == typeof(double?))
                    {
                        return 0f == (double)objValue;
                    }
                    else if (objType == typeof(long) || objType == typeof(long?))
                    {
                        return 0f == (long)objValue;
                    }
                    else if (objType == typeof(DateTime) || objType == typeof(DateTime?))
                    {
                        DateTime dt = (DateTime)objValue;
                        return DateTime.MinValue == dt || _MIN_DATE == dt;
                    }
                    else if (objType.IsEnum)
                    {
                        return Enum.Equals(Enum.ToObject(objType, 0), objValue);
                    }
                    throw new NotImplementedException("无法判定的类型[{objType.FullName}]");
                }
                return false;
            }
        }
    }
}
